package com.alibaba.yygh.user.controller;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.yygh.common.exception.YyghException;
import com.alibaba.yygh.common.result.R;
import com.alibaba.yygh.common.utils.JwtHelper;
import com.alibaba.yygh.model.user.UserInfo;
import com.alibaba.yygh.user.service.UserInfoService;
import com.alibaba.yygh.user.utils.ConstantPropertiesUtil;
import com.alibaba.yygh.user.utils.HttpClientUtils;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * description: WeixinApiController
 * @author: gql
 * @date: 2021/11
 */
@Controller
@RequestMapping("/api/user/wx")
@Slf4j
public class WeixinApiController {

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private RedisTemplate redisTemplate;


    @ApiOperation("1.生成微信登录二维码接口-返回二维码显示需要的数据")
    @GetMapping("getLoginParam")
    @ResponseBody // 返回JSON数据
    public R getWxLoginParam(HttpSession session) {
        try {
            Map<String, Object> map = new HashMap<>();
            map.put("appid", ConstantPropertiesUtil.WX_OPEN_APP_ID);
            map.put("scope", "snsapi_login");
            map.put("redirectUri", URLEncoder.encode(ConstantPropertiesUtil.WX_OPEN_REDIRECT_URL, "UTF-8"));
            map.put("state", System.currentTimeMillis() + "");//System.currentTimeMillis()+""
            return R.ok().data(map);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new YyghException(20001, "参数错误");
        }
    }

    @ApiOperation("2.扫码之后回调的方法")
    @GetMapping("callback")
    public String callback(String code, String state) {
        // 1.得到微信返回的临时票据code
        log.info("临时票据code = " + code);
        // 2.1 使用code值请求微信接口，获取openid和access_token
        StringBuffer baseAccessTokenUrl = new StringBuffer()
                .append("https://api.weixin.qq.com/sns/oauth2/access_token")
                .append("?appid=%s")
                .append("&secret=%s")
                .append("&code=%s")
                .append("&grant_type=authorization_code");
        String accessTokenUrl = String.format(baseAccessTokenUrl.toString(),
                ConstantPropertiesUtil.WX_OPEN_APP_ID,
                ConstantPropertiesUtil.WX_OPEN_APP_SECRET,
                code);
        try {
            // 2.2 发送httpclient请求
            String resultAccessToken = HttpClientUtils.get(accessTokenUrl);
            log.info("resultAccessToken:" + resultAccessToken);

            // 2.3 从返回字符串中获取openid和access_token
            JSONObject jsonObject = JSONObject.parseObject(resultAccessToken);
            String access_token = jsonObject.getString("access_token");
            String openid = jsonObject.getString("openid");

            // 3.1 使用openid和access_token再去访问微信接口,得到扫码人信息
            String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
                    "?access_token=%s" +
                    "&openid=%s";
            String userInfoUrl = String.format(baseUserInfoUrl, access_token, openid);

            // 3.2 发送httpclient请求
            String resultUserInfo = HttpClientUtils.get(userInfoUrl);
            log.info("resultUserInfo:" + resultUserInfo);

            // 3.3 从返回字符串中获取 用户昵称和用户头像
            JSONObject jsonObjectUserInfo = JSONObject.parseObject(resultUserInfo);
            String nickname = jsonObjectUserInfo.getString("nickname");
            String headimgurl = jsonObjectUserInfo.getString("headimgurl");

            // 4. 将扫码人微信信息添加到数据库
            // 4.1 根据openid查询是否存在微信信息
            UserInfo userInfo = this.userInfoService.getUserInfoByOpenId(openid);
            // userInfo为null代表是第一次扫码
            if (null == userInfo) {
                userInfo = new UserInfo();
                userInfo.setOpenid(openid);
                userInfo.setNickName(nickname);
                userInfo.setStatus(1);
                // 将扫码人信息添加到数据库中
                userInfoService.save(userInfo);
            }

            /**
             * 5.1 判断微信用户是否需要绑定
             * 从userInfo对象中获取手机号：
             *      获取到就不需要绑定,直接登录;
             *      获取不到就需要绑定
             */
            Map<String, String> map = new HashMap<>();
            if (StringUtils.isEmpty(userInfo.getPhone())) {// 需要绑定,传递openid
                map.put("openid", openid);
            } else {// 不需要绑定，不传递openid
                map.put("openid", "");
            }

            // 先取名称
            String name = userInfo.getName();
            // 名称为空取昵称
            if (StringUtils.isEmpty(name)) {
                name = userInfo.getNickName();
            }
            // 昵称为空,取手机号
            if (StringUtils.isEmpty(name)) {
                name = userInfo.getPhone();
            }
            // 将取得的值放入map
            map.put("name", name);

            // 6. 使用jwt生成token字符串
            String token = JwtHelper.createToken(userInfo.getId(), name);
            map.put("token", token);

            // 7. 扫码后重定向到前端页面
            return "redirect:http://localhost:3000/weixin/callback?token=" +
                    map.get("token") + "&openid=" + map.get("openid") + "&name=" +
                    URLEncoder.encode(map.get("name"), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }
}
